home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir41
/
startd22.zip
/
STARTD22.C
< prev
next >
Wrap
Text File
|
1993-06-05
|
19KB
|
507 lines
/*
* STARTD: A simple program to start a DOS session under OS/2 2.0.
* This program can be run from an OS/2 command prompt
*
* Last Modfied: 07/07/92
*
* Author: Norm Ross
* Jim Sauber
*
* Using the example code for BOOTA.C found in IBM DOCUMENT GBOF-2254
*
* This was written mainly to provide access to DOS SETTINGS for
* VDM sessions. Since I have disabled the WPS to free up the space,
* I can't specify DOS settings for my favorite DOS apps.
* STARTD is not meant to replace START but it does many of
* the same things...
*
* If you change this program and re-distribute it please leave this
* header intact and send the readme file with it.
*
* MODIFICATION HISTORY
*
* 07-Jul-1992 Norm Ross, npross@undergrad.uwaterloo.ca
* 1.00 : Initial version
* 25-Feb-1993 Jim Sauber
* 2.00 : Handles the creation of asynchronous DOS sessions
* 2.10 : Binds the parent to the child and handles icon started apps
* 06-Jun-1993 Jim Sauber
* 2.20 : Increased size of Environment to 4K and resolved OS/2 2.1 problems
*/
#define INCL_DOSSESMGR
#define INCL_DOSMISC
#define INCL_DOSPROCESS
#define INCL_WIN
#define INCL_DOSMEMMGR
#define INCL_WINSWITCHLIST
#include <os2.h>
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <string.h>
#include "pidinfo.h"
#define PID_BUFFER_SIZE 0x8000
#define DOS_PROGRAM_IDENT "SYSINIT" // Identifies a DOS program
#define WAIT_HOLD_TIME 5000 // Amount of time between checking for
// child process existence
PBYTE readEnv(PSZ pFileName);
void ChildProcess (PID) ;
PSZ pBootFailure = "Session could not be started.\r\n";
char szPgmInputs[512];
char szDosPgmInputs[512];
STARTDATA startd; /* Session start information */
ULONG ChildSessionID; /* Session and Process ID for new session*/
PID pidChildPid;
char fDebug ; /* flag whether to dump debug info */
void main(int argc, char *argv[])
{
USHORT rc, i ;
USHORT flagWin = 0, flagFs = 0, flagKeep = 0, flagNoCmd = 0;
fDebug = FALSE ;
/* ---- init startd struct defaults */
startd.Length = sizeof(STARTDATA);
startd.Related = SSF_RELATED_INDEPENDENT;
startd.FgBg = SSF_FGBG_FORE;
startd.TraceOpt = SSF_TRACEOPT_NONE;
startd.PgmTitle = NULL;
startd.PgmName = NULL;
startd.PgmInputs = NULL;
startd.TermQ = NULL;
startd.Environment = NULL;
startd.InheritOpt = SSF_INHERTOPT_PARENT;
startd.SessionType = SSF_TYPE_DEFAULT;
startd.PgmControl = SSF_CONTROL_VISIBLE;
/* ------ Process args */
while(--argc > 0)
{
char *arg;
switch(**++argv)
{
case '\"':
startd.PgmTitle = strtok(*argv, "\"");
break;
case '-':
case '/':
arg = (*argv)+1;
if (strlen(arg) == 1)
{
switch(*arg)
{
case 'n':
case 'N': flagNoCmd = 1; break;
case 'k':
case 'K': flagKeep = 1; break;
case 'c':
case 'C': break;
case 'f':
case 'F': startd.FgBg = SSF_FGBG_FORE; break;
case 'B':
case 'b': startd.FgBg = SSF_FGBG_BACK; break;
case 'i':
case 'I': startd.InheritOpt = SSF_INHERTOPT_SHELL; break;
case '?': usage(); break;
default:
fprintf(stderr, "Unrecognized option: %s\n", arg);
usage();
break;
}
}
else if (stricmp(arg, "DOS") == 0)
startd.SessionType = SSF_TYPE_VDM;
else if (stricmp(arg, "WIN") == 0)
flagWin = 1;
else if (stricmp(arg, "WAIT") == 0)
startd.Related = SSF_RELATED_CHILD;
else if (stricmp(arg, "FS") == 0)
flagFs = 1;
else if (stricmp(arg, "FG") == 0)
startd.FgBg = SSF_FGBG_FORE;
else if (stricmp(arg, "BG") == 0)
startd.FgBg = SSF_FGBG_BACK;
else if (stricmp(arg, "MAX") == 0)
startd.PgmControl |= SSF_CONTROL_MAXIMIZE;
else if (stricmp(arg, "MIN") == 0)
startd.PgmControl |= SSF_CONTROL_MINIMIZE;
else if (stricmp(arg, "INV") == 0)
startd.PgmControl |= SSF_CONTROL_INVISIBLE;
else if (stricmp(arg, "PM") == 0)
startd.SessionType = SSF_TYPE_PM;
else if (strnicmp(arg, "pos", 3) == 0)
{
char *s = strtok(arg, "=");
/* ---- I really should check strtok's return... */
startd.PgmControl |= SSF_CONTROL_SETPOS;
startd.InitXPos = atoi(strtok(NULL, ","));
startd.InitYPos = atoi(strtok(NULL, ","));
startd.InitXSize = atoi(strtok(NULL, ","));
startd.InitYSize = atoi(strtok(NULL, ""));
}
else if (stricmp(arg, "PGM") == 0)
{
char *p = szPgmInputs;
/* ---- strip quotes from name if there are any */
startd.PgmName = strtok(*argv, "\"");
/* ---- cat the rest of the args together to pass to pgm */
while (argc > 1)
{
argc--;
argv++;
strcpy(p, *argv);
p += strlen(*argv);
*p++ = ' '; /* put spaces between the args */
}
*p = '\0';
startd.PgmInputs = szPgmInputs;
break;
}
else if (stricmp(arg, "ICON") == 0)
{
startd.IconFile = *++argv;
argc--;
}
else if (stricmp(arg, "SF") == 0)
{
char *fname = *++argv;
argc--;
// if (access(fname, 0))
// fprintf(stderr, "Session File %s not found\n", fname);
startd.Environment = readEnv(fname);
}
else if (stricmp(arg, "DEBUG") == 0)
fDebug = TRUE ;
else
{
printf("Unrecognized option: %s\n", arg);
usage();
}
break;
default:
{
char *p = szPgmInputs;
startd.PgmName = *argv;
/* ---- cat the rest of the args together to pass to pgm */
while (argc > 1)
{
argc--;
argv++;
strcpy(p, *argv);
p += strlen(*argv);
*p++ = ' '; /* put spaces between the args */
}
*p = '\0';
startd.PgmInputs = szPgmInputs;
break;
}
} /* switch */
} /* while */
/* ------ Start thru Command processor */
if ((startd.PgmName!=NULL)&&(startd.SessionType!=SSF_TYPE_PM)&&(!flagNoCmd))
{
if (flagKeep)
strcpy(szDosPgmInputs, "/k ");
else
strcpy(szDosPgmInputs, "/c ");
strcat(szDosPgmInputs, startd.PgmName);
strcat(szDosPgmInputs, " ");
strcat(szDosPgmInputs, startd.PgmInputs);
startd.PgmInputs = szDosPgmInputs;
startd.PgmName = NULL;
}
/* ------ Set the correct session type */
if (flagWin)
{
switch(startd.SessionType)
{
case SSF_TYPE_DEFAULT:
startd.SessionType = SSF_TYPE_WINDOWABLEVIO;
break;
case SSF_TYPE_VDM:
startd.SessionType = SSF_TYPE_WINDOWEDVDM;
break;
case SSF_TYPE_PM:
break;
} /* switch */
} /* if */
else if (flagFs)
{
switch(startd.SessionType)
{
case SSF_TYPE_DEFAULT: startd.SessionType = SSF_TYPE_FULLSCREEN; break;
case SSF_TYPE_VDM: break;
case SSF_TYPE_PM: break;
} /* switch */
} /* elseif */
/* if debug is set, then dump all settings */
if (fDebug)
{
printf ("Related = %d\n", startd.Related) ;
printf ("FgBg = %d\n", startd.FgBg) ;
printf ("TraceOpt = %d\n", startd.TraceOpt) ;
printf ("PgmTitle = ") ;
if (startd.PgmTitle != NULL)
for (i = 0; startd.PgmTitle[i] != 0; ++i)
printf ("%c", startd.PgmTitle[i]) ;
printf ("\n") ;
printf ("PgmName =") ;
if (startd.PgmName != NULL)
for (i = 0; startd.PgmName[i] != 0; ++i)
printf ("%c", startd.PgmName[i]) ;
printf ("\n") ;
printf ("PgmInputs =") ;
if (startd.PgmInputs != NULL)
for (i = 0; startd.PgmInputs[i] != 0; ++i)
printf ("%c", startd.PgmInputs[i]) ;
printf ("\n") ;
printf ("TermQ =") ;
if (startd.TermQ != NULL)
for (i = 0; startd.TermQ[i] != 0; ++i)
printf ("%c", startd.TermQ[i]) ;
printf ("\n") ;
printf ("Environment= ") ;
if (startd.Environment != NULL)
for (i = 0; startd.Environment[i] != 10; ++i)
printf ("%c", startd.Environment[i]) ;
printf ("\n") ;
printf ("InheritOpt = %d\n", startd.InheritOpt) ;
printf ("SessionType= %d\n", startd.SessionType) ;
printf ("PgmControl = %d\n", startd.PgmControl) ;
}
/* ------ Start the Session */
rc = DosStartSession( &startd, &ChildSessionID, &pidChildPid );
if(rc)
/* ------ Print out failure message */
DosPutMessage(1,strlen(pBootFailure),pBootFailure);
else if (startd.Related == SSF_RELATED_CHILD)
ChildProcess (pidChildPid) ;
return;
}
#define MAXENV 4096
/************************************************************************/
// Read the DOS environment file and create the environment string
/************************************************************************/
PBYTE readEnv(PSZ fname)
{
FILE *fptr;
PBYTE env = (PBYTE)malloc(MAXENV);
PBYTE p = env;
char *i ;
fptr = fopen(fname, "rb");
if (fptr == (FILE *)NULL)
{
fprintf(stderr, "\nFile %s cannot be found\n");
exit(-1);
}
// If the env flag is DOS_VERSION, then need to concatenate all the strings
// together to form 1 environment string. If only 0x0a terminates the input
// then remove the NULL, concatenate the 0x0a and the string and add a
// NULL
while (fgets(p, 80, fptr))
{
p+=strlen(p);
// if last 2 chars are crlf then remove them, if last char is lf, then
// keep it
if (*(p-2) == '\r' && *(p-1) == '\n')
{
*(p-2)='\0';
--p ;
} /* if */
// *(p-1)='\0';
if (p>env + 4096)
{
fprintf(stderr, "ERROR: too many settings\n");
fflush(stderr);
exit(-1);
}
} /* while */
realloc(env, p-env);
fclose (fptr) ;
return(env);
}
/************************************************************************/
// Display for the user the usage information
/************************************************************************/
usage( void )
{
fprintf(stderr, "STARTD VERSION 2.2 by Norm Ross & Jim Sauber Copyright (c) 1993\n\n");
fprintf(stderr, "startd [\"program title\"] [/BG /C /DOS /F /FS /I /ICON iconfile /INV /K /MAX\n\t /MIN /PGM POS=x,y,x1,y1 /SF settingsfile /WIN] [command ...]\n\n");
fprintf(stderr, "\t/B[G]\t start session in background\n");
fprintf(stderr, "\t/C\t close session upon completion\n");
fprintf(stderr, "\t/DOS\t start a dos session\n");
fprintf(stderr, "\t/F[G]\t start session in foreground\n");
fprintf(stderr, "\t/FS\t start a full screen session\n");
fprintf(stderr, "\t/I\t sets SSF_INHERTOPT_SHELL\n");
fprintf(stderr, "\t/ICON\t uses the specified icon file\n");
fprintf(stderr, "\t/INV\t start the application invisibly\n");
fprintf(stderr, "\t/K\t keep the session around after it is finished\n");
fprintf(stderr, "\t/MAX\t start maximized\n");
fprintf(stderr, "\t/MIN\t start minimized\n");
fprintf(stderr, "\t/N\t don't start indirectly through command processor\n");
fprintf(stderr, "\t/PGM\t the next argument is the program name\n");
fprintf(stderr, "\t/PM\t start a PM program\n");
fprintf(stderr, "\t/POS=x,y,x1,y1\t specify window position and size\n");
fprintf(stderr, "\t/SF\t read the specified dos settings file\n");
fprintf(stderr, "\t/WIN\t start a windowed session\n");
fprintf(stderr, "\t/WAIT\t doesn't work\n");
exit(1);
}
/************************************************************************/
// Function: To start asynchronous process
// The function searches the process list and switch list until it finds
// an ancestor of the current process in the switch list. It then removes
// that process from the switch list and if it is a window, minmizes it.
/************************************************************************/
void ChildProcess(PID pidChildPid)
{
USHORT usActiveProcesses ; /* count of active processes */
PBUFFHEADER pbh ; /* buffer for task info */
PPROCESSINFO ppiLocal ; /* child process info */
BOOL fPidFound ; /* flag whether child process is found */
PTIB pTib ; /* Tib info of current process */
PPIB pPib ; /* Pib info of current process */
HAB hab ; /* handle to switch list */
HSWITCH hswitch ; /* handle to switch entry */
ULONG cbItems, cbBuf ; /* sizeof of Process buffer */
PBYTE pBase ; /* pointer to memory */
PSWBLOCK pswblk ; /* pointer to allocated memory */
PSWENTRY pSwitchEntry ; /* pointer to each switch entry in list */
SHORT i ; /* misc counter */
ULONG ulCurrentType ; /* current session type */
PID pidParentPid ; /* current process' immediate parent's PID */
PID pidCurrentPid ; /* PID of this process */
PID pidAncestorPid ; /* PID of an ancestor in the switch list */
HWND hwndAncestorFrame ; /* frame hwnd of the ancestor in the switch list */
HSWITCH hAncestorSwitch ; /* switch entry handle to displayed ancestor */
SWCNTRL swParentControl ; /* switch entry info parent */
SWCNTRL swAncestorControl ; /* switch entry of ancestor */
STATUSDATA sdSetSessionData ; /* DosSetSession status data */
USHORT rc ; /* misc return code */
rc = DosGetInfoBlocks (&pTib, &pPib) ;
ulCurrentType = pPib->pib_ultype ;
pidCurrentPid= pPib->pib_ulpid ;
pidParentPid = pPib->pib_ulppid ;
/* allocate memory for Process list */
rc = DosAllocMem((PPVOID) &pBase, (ULONG) 40000, PAG_READ | PAG_WRITE) ;
rc = DosSubSetMem (pBase, DOSSUB_INIT | DOSSUB_SPARSE_OBJ, 4000) ;
/* get the process list */
pbh = malloc (PID_BUFFER_SIZE) ;
rc = DosQProcStatus (pbh, PID_BUFFER_SIZE) ;
ppiLocal = pbh->ppi ;
/* get the switch list */
cbItems = WinQuerySwitchList (hab, NULL, 0) ;
cbBuf = (cbItems * sizeof(SWENTRY)) + sizeof(HSWITCH) ;
rc = DosSubAllocMem((PVOID) pBase, (PPVOID) &pswblk, (ULONG) cbBuf) ;
do
{
rc = WinQuerySwitchList (hab, pswblk, cbBuf) ;
/* search the switch list to find an ancestor of the current process */
/* pidAncestorPid = -1 means no ancestor found yet */
pidAncestorPid = -1 ;
pSwitchEntry = &(pswblk->aswentry[0]) ;
for (i = 0; i < cbItems && pidAncestorPid == -1; ++i, ++pSwitchEntry)
{
hswitch = pSwitchEntry->hswitch ;
rc = WinQuerySwitchEntry (hswitch, &swParentControl) ;
/* if found current pid in the switch list */
if (pidCurrentPid == swParentControl.idProcess)
{
pidAncestorPid = swParentControl.idProcess ;
hwndAncestorFrame = swParentControl.hwnd ;
}
/* if found parent pid in the switch list */
if (pidParentPid == swParentControl.idProcess)
{
pidAncestorPid = swParentControl.idProcess ;
hwndAncestorFrame = swParentControl.hwnd ;
}
}
/* if ancestor not found in the switch list this time, go back */
/* one more generation */
if (pidAncestorPid == -1) {
fPidFound = FALSE ;
while(ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR && !fPidFound){
++usActiveProcesses ;
if (ppiLocal->pid == pidParentPid)
{
fPidFound = TRUE ;
pidParentPid = ppiLocal->pidParent ;
} /* endif */
ppiLocal = (PPROCESSINFO) (ppiLocal->ptiFirst+ppiLocal->usThreadCount );
}
} else {
} /* endif */
} while ( pidAncestorPid == -1 && pidParentPid != 0); /* enddo */
// hAncestorSwitch = WinQuerySwitchHandle (hwndAncestorFrame, 0) ;
// rc = WinQuerySwitchEntry (hswitch, &swAncestorControl) ;
// swAncestorControl.uchVisibility = SWL_INVISIBLE;
// swAncestorControl.fbJump = SWL_NOTJUMPABLE;
// WinChangeSwitchEntry (hAncestorSwitch, &swAncestorControl) ;
/* If this is a windowed session, minimize it */
if (ulCurrentType == 2)
rc = WinPostMsg (hwndAncestorFrame, WM_SYSCOMMAND,
MPFROMSHORT(SC_MINIMIZE), NULL) ;
/* Set so when the parent's icon is clicked, the child shows up */
sdSetSessionData.Length = 6 ;
sdSetSessionData.SelectInd = 2 ;
sdSetSessionData.BondInd = 1 ;
DosSetSession (ChildSessionID, &sdSetSessionData) ;
/* Wait for child to finish */
do
{
DosSleep (WAIT_HOLD_TIME) ;
rc = DosQProcStatus (pbh, PID_BUFFER_SIZE) ;
ppiLocal = pbh->ppi ;
usActiveProcesses = 0 ;
fPidFound = FALSE ;
while(ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR && !fPidFound)
{
++usActiveProcesses ;
if (ppiLocal->pid == pidChildPid)
fPidFound = TRUE ;
ppiLocal = (PPROCESSINFO) (ppiLocal->ptiFirst+ppiLocal->usThreadCount );
}
} while (fPidFound) ;
swAncestorControl.uchVisibility = SWL_VISIBLE;
swAncestorControl.fbJump = SWL_JUMPABLE;
WinChangeSwitchEntry (hAncestorSwitch, &swAncestorControl) ;
if (ulCurrentType == 2)
rc = WinPostMsg (hwndAncestorFrame, WM_SYSCOMMAND,
MPFROMSHORT(SC_RESTORE), NULL) ;
return ;
}